1 // Ternary search and binary search. Accepted.
24 template <class T
> string
toStr(const T
&x
) { stringstream s
; s
<< x
; return s
.str(); }
25 template <class T
> int toInt(const T
&x
) { stringstream s
; s
<< x
; int r
; s
>> r
; return r
; }
27 #define For(i, a, b) for (int i=(a); i<(b); ++i)
28 #define foreach(x, v) for (typeof (v).begin() x = (v).begin(); x != (v).end(); ++x)
29 #define D(x) cout << #x " = " << (x) << endl
32 #define MAXBUFF (1<<20)
33 char buffer
[MAXBUFF
], *p
= buffer
+MAXBUFF
;
34 char buffer2
[MAXBUFF
], *p2
= buffer2
;
36 inline char read_char() {
37 if( p
== buffer
+MAXBUFF
) {
38 fread( buffer
, 1, MAXBUFF
, stdin
);
44 inline int read_int() {
46 while( !isdigit(c
) and c
!= '-' ) c
= read_char();
47 int sign
= c
== '-' ? -1 : +1;
48 if (c
== '-') c
= read_char();
50 while( isdigit(c
= read_char()) ) ret
= ret
* 10 + c
-'0';
55 fwrite( buffer2
, 1, p2
-buffer2
, stdout
);
59 inline void write( char c
) {
60 if( p2
== buffer2
+MAXBUFF
) {
61 fwrite( buffer2
, 1, MAXBUFF
, stdout
);
68 const double EPS
= 1e-10;
70 int cmp(double x
, double y
= 0, double tol
= EPS
){
71 return( x
<= y
+ tol
) ? (x
+ tol
< y
) ? -1 : 0 : 1;
76 point(){} point(double x
, double y
, double z
) : x(x
), y(y
), z(z
) {}
83 inline double dist(const point
&a
, const point
&b
) {
84 double dx
= b
.x
- a
.x
, dy
= b
.y
- a
.y
, dz
= b
.z
- a
.z
;
85 return sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
88 point
positionAt(int p
, double t
) {
91 int i
= upper_bound(D
[p
], D
[p
] + P
[p
].size(), d
) - D
[p
] - 1;
94 double distance
= dist(P
[p
][i
], P
[p
][i
+1]);
95 //assert(cmp(s + distance, d) >= 0);
97 if (cmp(distance
, 0.0) > 0) {
98 double dx
= P
[p
][i
+1].x
- P
[p
][i
].x
;
99 double dy
= P
[p
][i
+1].y
- P
[p
][i
].y
;
100 double dz
= P
[p
][i
+1].z
- P
[p
][i
].z
;
101 ans
.x
+= (d
- s
) * dx
/ distance
;
102 ans
.y
+= (d
- s
) * dy
/ distance
;
103 ans
.z
+= (d
- s
) * dz
/ distance
;
105 //assert(cmp(s + dist(P[p][i], ans), d) == 0);
109 double distanceAtTime(double t
) {
110 point p0
= positionAt(0, t
);
111 point p1
= positionAt(1, t
);
115 double touchAtTime(double t
) {
116 return cmp(distanceAtTime(t
), 0.0 + R
[0] + R
[1]) <= 0;
119 double findClosestTime(double left
, double right
) {
120 // double bestTime = -1, bestDistance = 1e200;
121 // for (double t = left; t <= right; t += 0.5) {
122 // double d = distanceAtTime(t);
123 // printf("At time %lf, distance is %lf\n", t, d);
124 // if (cmp(d, bestDistance) < 0) {
130 while (cmp(left
, right
) < 0) {
131 double t1
= (2 * left
+ right
) / 3;
132 double t2
= (2 * right
+ left
) / 3;
133 double d1
= distanceAtTime(t1
);
134 double d2
= distanceAtTime(t2
);
141 double ans
= (left
+ right
) / 2;
142 //printf("Best is at time %lf, where distance is %lf\n", ans, distanceAtTime(ans));
147 int casos
= IO::read_int(); while (casos
--) {
148 for (int p
= 0; p
< 2; ++p
) {
150 R
[p
] = IO::read_int(), V
[p
] = IO::read_int(), k
= IO::read_int();
152 for (int i
= 0; i
< k
; ++i
) {
153 P
[p
][i
].x
= IO::read_int(), P
[p
][i
].y
= IO::read_int(), P
[p
][i
].z
= IO::read_int();
155 P
[p
].push_back( point(0, 0, 0) );
158 double totalTime
= 1e100
;
159 for (int p
= 0; p
< 2; ++p
) {
161 for (int i
= 1; i
< P
[p
].size(); ++i
) {
162 D
[p
][i
] = D
[p
][i
-1] + dist(P
[p
][i
-1], P
[p
][i
]);
164 totalTime
= min(totalTime
, D
[p
][P
[p
].size() - 1] / V
[p
]);
167 // point p1 = positionAt(0, totalTime);
168 // point p2 = positionAt(1, totalTime);
169 // printf("<%lf, %lf, %lf>\n", p1.x, p1.y, p1.z);
170 // printf("<%lf, %lf, %lf>\n", p2.x, p2.y, p2.z);
171 vector
<double> times
;
172 for (int p
= 0; p
< 2; ++p
) {
174 times
.push_back(0.0);
175 for (int i
= 0; i
< P
[p
].size() - 1; ++i
) {
176 d
+= dist(P
[p
][i
], P
[p
][i
+1]);
178 if (cmp(t
, totalTime
) <= 0) times
.push_back(d
/ V
[p
]);
181 sort(times
.begin(), times
.end());
182 //For(i, 0, times.size() - 1) assert(cmp(times[i], times[i + 1]) <= 0);
183 // for (int i = 0; i < times.size(); ++i) {
184 // printf("%lf ", times[i]);
189 for (int i
= 0; i
< times
.size() - 1; ++i
) {
190 //printf("\nInterval from time (%lf, %lf):\n", times[i], times[i+1]);
191 const double &t
= times
[i
];
192 if (touchAtTime(t
)) {
193 //printf("They touch at time %lf, continuing.\n", t);
196 double closestTime
= findClosestTime(t
, times
[i
+1]);
197 if (touchAtTime(closestTime
)) {
201 if (touchAtTime(0.0)) ans
++;